/***************************************
 *Trabalho de Recuperação de Informação*
 *             Grupo:                  *
 *     Jayme Siqueira Barbosa          *
 *     Felipe Rooke                    *
 *     Helena Maia                     *
 ***************************************/

#include <stdio.h>
#include <stdlib.h>
#include "simbol.h"
#include "string.h"
#include "basic.h"
#include "time.h"
#include "Rtree.hpp"
#define DEFAULT_HITS 30
int totalDescriptors = 0;
///arg1 caminho para fvec
///arg2 b = basica, r = R*, s = SRTree
///arg3 k = numero de resultados a serem retornados
///Objetivo1: Ler fvec e armazenar vetor de cada vídeo
///Objetivo2: Testar arg2 e deixar em branco pra eu encaixar a minha função --> Parâmetro lista de vetores e tamanho da lista
///Objetivo3:

float precisao(DescriptorResults *dr, int comecos[7], int movimento, int k){
    DescriptorResults *aux;
    float prec = 0;
    while(dr!=NULL){
        if(dr->descriptor->id >= comecos[movimento] && dr->descriptor->id < comecos[movimento+1]) prec++;
        aux = dr;
        dr = dr->next;
        free(aux);
    }
    return (prec/k);
}


//realiza a leitura do arquivo e devolve uma lista de descritores
Descriptor *_import(FILE *fileIn){
    Descriptor *head = NULL, *current = NULL;
    //int j=0;
    totalDescriptors = 0;
    int size;

    while (!feof(fileIn)){
        Descriptor * newd = (Descriptor*)malloc(sizeof(Descriptor));
        //newd->id = j*2391+i;
        newd->id = totalDescriptors;
        newd->next = NULL;

        fread(&size, 1, sizeof(unsigned int), fileIn);//todos devem ter o mesmo tamanho = DESCRIPTOR_SIZE, então descarta essa leitura
        if (size != DESCRIPTOR_SIZE)
            fprintf(stderr, "ERRO: Descritor %d possui tamanho %d\n", totalDescriptors, size);
        fread(newd->descr, DESCRIPTOR_SIZE, sizeof(float), fileIn);

        if(head == NULL){
            head = newd;
            current = newd;
        }
        else{
            current->next = newd;
            current = newd;
        }
        totalDescriptors++;

        /*if (i == 2391){
            if (j < 500)
                fseek(fileIn, 0*(size*sizeof(float)+sizeof(unsigned int)), SEEK_SET);//acho que não precisa, iremos ler o arquivo inteiro
            j++;
            i =0;
        }*/
    }
    return head;
}

No* importRestrela(Descriptor * descriptors){
    No* rtree = new No();
    Ponto* p;

    while (descriptors != NULL) {
        p = new Ponto(DESCRIPTOR_SIZE);

        for (int i = 0; i < DESCRIPTOR_SIZE; i++) p->setCoord(i, descriptors->descr[i]);


        rtree = rtree->insere(rtree, p, CLOSE_REINSERT, false);

        descriptors = descriptors->next;

    }

    return rtree;
}

int main(int argc, char* argv[]){
    FILE *fileIn = NULL;
    FILE *fileDescri = NULL;
    char *fileNameIn = NULL;
    char *fileNameDescri = NULL;
    char option;
    int k;

    if(argc > 1) {
        if(strlen(argv[1]) > 0) {
            fileNameIn = (char *) malloc(sizeof(char) * strlen(argv[1]));
            sprintf(fileNameIn,"%s",argv[1]);

            if (!(fileIn = fopen(fileNameIn, "rb"))) {
                fprintf(stderr, "Erro ao tentar ler o arquivo... \n");
                free(fileNameIn);
                exit(-1);
            }
        }
    }
    else{
        fprintf(stderr, "ESPECIFIQUE UM ARQUIVO DE ENTRADA!\n");
        return -1;
    }

    ///Verifica se existe argumento o tipo de estrutura a utilizar
    if(argc > 2){
        sprintf(&option,"%s",argv[2]);
    }

    else {
        fprintf(stderr, "ESTRUTURA NAO ESCOLHIDA, BUSCA GULOSA ATIVADA POR PADRAO!\n");
        option = 'b';
    }

    if(argc > 3){
        k = atoi(argv[3]);
    }
    else {
        k = DEFAULT_HITS;
    }


    float buscar[DESCRIPTOR_SIZE];

    if(argc > 4){
        if(strlen(argv[4]) > 0) {
            fileNameDescri = (char *) malloc(sizeof(char) * strlen(argv[4]));
            sprintf(fileNameDescri,"%s",argv[4]);

            if (!(fileDescri = fopen(fileNameDescri, "rb"))) {
                fprintf(stderr, "Erro ao tentar ler o arquivo... \n");
                free(fileDescri);
                exit(-1);
            }
            else{

                float f;

                for (int i = 0; i< DESCRIPTOR_SIZE; i++){
                    fscanf(fileDescri, "%f ", &f);
                    buscar[i] = f;
                }
            }
        }
    }
    else {
        fprintf(stdout,"Arquivo descritor nao informado!");
    }

    ///lista de descritores
    Descriptor * descriptors;
    if(fileIn){
        descriptors = _import(fileIn);
        fclose(fileIn);
    }
    else{
        fprintf(stderr, "Arquivo não aberto, Impossivel continuar.");
        return 1;
    }

    //Estruturas
    DescriptorResults *dr;
    No * rEstrela;
    clock_t c2, c1;
    float tempo;

    switch (option){
        case 'b':{///estrura básica escolhida
            c1 = clock();
            dr = greedySearch(descriptors, buscar, k);
            c2 = clock();
            tempo = (c2 - c1)*1000/CLOCKS_PER_SEC;;

            //fprintf(stdout,"%d mais parecidos com: %s:\n",k, fileNameDescri);
            while (dr != NULL){
                ///fprintf(stdout,"%d %f\n", dr->descriptor->id % 2391, dr->distance);
                fprintf(stdout,">> %d %f\n", dr->descriptor->id, dr->distance);
                dr = dr->next;
            }

            fprintf(stdout,"tempo de busca %f\n", tempo);

            break;
        }

        case 'r':{///estrurura R* escolhida
            rEstrela = importRestrela(descriptors);
            printf("importado na R Estrela\n");


            dr = NULL;
            c1 = clock();

            kNearestNeighbor(rEstrela, &dr, buscar, k, true, false);


            c2 = clock();
            tempo = (c2 - c1)*1000/CLOCKS_PER_SEC;;




            while (dr != NULL){
                fprintf(stdout,">> %d %f\n", dr->descriptor->id, dr->distance);
                dr = dr->next;
            }

            fprintf(stdout,"tempo de busca %f\n", tempo);



            break;
        }

        case 'm':{///medidas para relatorio
            int queries[6][10]={{25, 77, 103, 144, 169, 201, 246, 300, 321, 348}, ///box
                                {398, 410, 433,467, 527, 559, 624, 689, 754, 788}, ///handclap
                                {795, 838, 861, 896, 961, 993, 1058, 1091, 1156, 1188}, ///handwave
                                {1198, 1247, 1296, 1323, 1377,1409, 1450, 1488, 1550, 1583}, ///jogging
                                {1601, 1637, 1700, 1743, 1799, 1823, 1856, 1895, 1947, 1989}, ///run
                                {1993, 2047, 2068, 2124, 2154, 2171, 2223, 2287, 2340, 2386}}; ///walk
            int comecos[7] = {0, 397, 793, 1191, 1591, 1991, 2391};

            Descriptor *atual = descriptors, *anterior = NULL;
            printf("%d", descriptors->id);
            FILE *dadosLista = fopen("dadosLista.out", "w");
            FILE *dadosRtree = fopen("dadosRtree.out", "w");
            rEstrela = importRestrela(descriptors);
            float prec, precMediaLista = 0.0, precMediaRtree=0.0;
            for(int i = 0; i < 6; i++){
                for(int j = 0; j < 10; j++){
                    while(atual!=NULL && atual->id!=queries[i][j]) {
                        anterior = atual;
                        atual = atual->next;
                    }
                    if(atual!=NULL){
                        anterior->next = atual->next;
                        ///Precisao Lista
                        dr = greedySearch(descriptors, atual->descr, k);
                        prec = precisao(dr, comecos, i, k);
                        precMediaLista+=prec;
                        printf("Id %d %.f\%\n", queries[i][j], prec*100);
                        fprintf(dadosLista, "%d %.2f\n", queries[i][j], prec);

                        dr = NULL;
                        kNearestNeighbor(rEstrela,&dr,atual->descr, k+1, true, false);
                        prec = precisao(dr->next, comecos, i, k);
                        free(dr);
                        precMediaRtree+=prec;
                        printf("Id %d %.f\%\n", queries[i][j], prec*100);
                        fprintf(dadosRtree, "%d %.2f\n", queries[i][j], prec);

                        anterior->next = atual;
                    }
                }
            }
            precMediaLista/=60;
            precMediaRtree/=60;
            printf("Média lista %.f\%\n", precMediaLista*100);
            printf("Média Rtree %.f\%\n", precMediaRtree*100);
            fprintf(dadosLista, "AVG %f", precMediaLista);
            fprintf(dadosRtree, "AVG %f", precMediaRtree);
            fclose(dadosLista);
            fclose(dadosRtree);
        }
        case 'n':

        break;

        default: break;
    }

    return 0;
}
